package com.agileboot.attendance.domain.order;

import com.agileboot.attendance.domain.order.db.AttOrderService;
import com.agileboot.attendance.domain.order.dto.OrderDTO;
import com.agileboot.attendance.domain.order.dto.OrderImportDTO;
import com.agileboot.attendance.domain.order.dto.OrderQuery;
import com.agileboot.attendance.domain.order.dto.OrderRequest;
import com.agileboot.attendance.domain.order.entity.AttOrderEntity;
import com.agileboot.attendance.domain.order.model.OrderModel;
import com.agileboot.attendance.domain.order.model.OrderModelFactory;
import com.agileboot.attendance.domain.project.db.service.AttProjectService;
import com.agileboot.attendance.domain.project.entity.AttProjectEntity;
import com.agileboot.attendance.domain.supplier.db.AttSupplierService;
import com.agileboot.attendance.domain.supplier.db.AttSupplierEntity;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.utils.poi.ExportImportService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订单应用服务
 *
 * @author agileboot
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderApplicationService {

    private final AttOrderService orderService;
    private final AttProjectService projectService;
    private final AttSupplierService supplierService;
    private final OrderModelFactory orderModelFactory;
    private final ExportImportService exportImportService;

    /**
     * 获取订单列表
     *
     * @param query 查询参数
     * @return 订单列表分页结果
     */
    public PageDTO<OrderDTO> getOrderList(OrderQuery query) {
        Page<AttOrderEntity> page = orderService.getOrderList(query);
        List<OrderDTO> orderDTOList = page.getRecords().stream()
                .map(order -> {
                    OrderModel model = OrderModel.fromEntity(order);
                    model.setProjectEntity(projectService.getById(order.getProjectId()));
                    model.setSupplierEntity(supplierService.getById(order.getSupplierId()));
                    return model.toDTO();
                })
                .collect(Collectors.toList());

        return new PageDTO<>(orderDTOList, page.getTotal());
    }
    
    /**
     * 获取订单列表用于导出
     *
     * @param query 查询参数
     * @return 订单列表
     */
    public List<OrderDTO> getOrderListForExport(OrderQuery query) {
        // 设置为不分页查询
        query.setPageNum(1);
        query.setPageSize(Integer.MAX_VALUE);
        
        PageDTO<OrderDTO> pageDTO = getOrderList(query);
        return pageDTO.getRows();
    }

    /**
     * 获取订单详情
     *
     * @param orderId 订单ID
     * @return 订单详情
     */
    public OrderDTO getOrderDetail(Long orderId) {
        OrderModel model = orderModelFactory.loadById(orderId);
        return model.toDTO();
    }

    /**
     * 添加订单
     *
     * @param request 订单请求参数
     */
    @Transactional(rollbackFor = Exception.class)
    public void addOrder(OrderRequest request) {
        // 检查项目是否存在
        if (projectService.getById(request.getProjectId()) == null) {
            throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, request.getProjectId(), "项目");
        }

        // 检查供应商是否存在
        if (supplierService.getById(request.getSupplierId()) == null) {
            throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, request.getSupplierId(), "供应商");
        }

        // 检查订单编码是否重复
        if (orderService.isOrderCodeDuplicated(request.getOrderCode(), null)) {
            throw new ApiException(ErrorCode.Business.SUPPLIER_CODE_IS_NOT_UNIQUE, request.getOrderCode());
        }

        // 创建订单模型并保存
        OrderModel model = OrderModel.fromRequest(request);
        orderService.save(model.getEntity());
    }

    /**
     * 更新订单
     *
     * @param request 订单请求参数
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(OrderRequest request) {
        // 检查订单是否存在
        OrderModel model = orderModelFactory.loadById(request.getOrderId());

        // 检查项目是否存在
        if (projectService.getById(request.getProjectId()) == null) {
            throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, request.getProjectId(), "项目");
        }

        // 检查供应商是否存在
        if (supplierService.getById(request.getSupplierId()) == null) {
            throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, request.getSupplierId(), "供应商");
        }

        // 检查订单编码是否重复
        if (orderService.isOrderCodeDuplicated(request.getOrderCode(), request.getOrderId())) {
            throw new ApiException(ErrorCode.Business.SUPPLIER_CODE_IS_NOT_UNIQUE, request.getOrderCode());
        }

        // 更新订单
        model.updateEntity(request);
        orderService.updateById(model.getEntity());
    }

    /**
     * 删除订单
     *
     * @param orderId 订单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrder(Long orderId) {
        // 检查订单是否存在
        OrderModel model = orderModelFactory.loadById(orderId);
        
        // TODO: 检查订单是否可以删除（如果订单已经有关联数据，可能不允许删除）
        
        orderService.removeById(orderId);
    }
    
    /**
     * 完成订单
     *
     * @param orderId 订单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void completeOrder(Long orderId) {
        OrderModel model = orderModelFactory.loadById(orderId);
        
        // 检查当前状态
        if (!"0".equals(model.getEntity().getStatus())) {
            throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "只有进行中的订单才能标记为完成");
        }
        
        model.getEntity().setStatus("1"); // 设置为已完成
        model.getEntity().setUpdateTime(new Date());
        orderService.updateById(model.getEntity());
    }
    
    /**
     * 取消订单
     *
     * @param orderId 订单ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(Long orderId) {
        OrderModel model = orderModelFactory.loadById(orderId);
        
        // 检查当前状态
        if (!"0".equals(model.getEntity().getStatus())) {
            throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "只有进行中的订单才能取消");
        }
        
        model.getEntity().setStatus("2"); // 设置为已取消
        model.getEntity().setUpdateTime(new Date());
        orderService.updateById(model.getEntity());
    }
    
    /**
     * 导入订单数据
     *
     * @param file 导入文件
     */
    @Transactional(rollbackFor = Exception.class)
    public void importOrderData(MultipartFile file) {
        // 使用通用导入服务读取文件
        List<OrderImportDTO> importList = exportImportService.importExcel(file, OrderImportDTO.class);
        
        // 检查导入数据是否为空
        if (importList == null || importList.isEmpty()) {
            throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "导入数据为空");
        }
        
        // 预处理: 获取所有项目和供应商的映射关系
        Map<String, Long> projectNameIdMap = getProjectNameIdMap();
        Map<String, Long> supplierNameIdMap = getSupplierNameIdMap();
        
        // 逐条处理导入数据
        List<AttOrderEntity> orderEntities = new ArrayList<>();
        for (int i = 0; i < importList.size(); i++) {
            OrderImportDTO importDTO = importList.get(i);
            
            // 基础数据验证
            if (importDTO.getOrderCode() == null || importDTO.getOrderCode().isEmpty()) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行订单编码不能为空");
            }
            if (importDTO.getProjectName() == null || importDTO.getProjectName().isEmpty()) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行项目名称不能为空");
            }
            if (importDTO.getSupplierName() == null || importDTO.getSupplierName().isEmpty()) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行供应商名称不能为空");
            }
            if (importDTO.getStartDate() == null) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行起始日期不能为空");
            }
            if (importDTO.getSettlementCycleName() == null || importDTO.getSettlementCycleName().isEmpty()) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行结算周期不能为空");
            }
            
            // 检查订单编码是否重复
            if (orderService.isOrderCodeDuplicated(importDTO.getOrderCode(), null)) {
                throw new ApiException(ErrorCode.Business.SUPPLIER_CODE_IS_NOT_UNIQUE, importDTO.getOrderCode());
            }
            
            // 获取项目ID
            Long projectId = projectNameIdMap.get(importDTO.getProjectName());
            if (projectId == null) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行的项目名称在系统中不存在: " + importDTO.getProjectName());
            }
            
            // 获取供应商ID
            Long supplierId = supplierNameIdMap.get(importDTO.getSupplierName());
            if (supplierId == null) {
                throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行的供应商名称在系统中不存在: " + importDTO.getSupplierName());
            }
            
            // 解析结算周期
            String settlementCycle;
            switch (importDTO.getSettlementCycleName()) {
                case "月":
                    settlementCycle = "1";
                    break;
                case "季":
                    settlementCycle = "2";
                    break;
                case "年":
                    settlementCycle = "3";
                    break;
                case "自定义":
                    settlementCycle = "4";
                    break;
                default:
                    throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行的结算周期不正确，可选值为：月、季、年、自定义");
            }
            
            // 解析状态
            String status = "0"; // 默认为进行中
            if (importDTO.getStatusName() != null && !importDTO.getStatusName().isEmpty()) {
                switch (importDTO.getStatusName()) {
                    case "进行中":
                        status = "0";
                        break;
                    case "已完成":
                        status = "1";
                        break;
                    case "已取消":
                        status = "2";
                        break;
                    default:
                        throw new ApiException(ErrorCode.Business.COMMON_UNSUPPORTED_OPERATION, "第" + (i + 1) + "行的状态不正确，可选值为：进行中、已完成、已取消");
                }
            }
            
            // 创建订单实体
            AttOrderEntity entity = new AttOrderEntity();
            entity.setOrderCode(importDTO.getOrderCode());
            entity.setProjectId(projectId);
            entity.setSupplierId(supplierId);
            entity.setStartDate(importDTO.getStartDate());
            entity.setEndDate(importDTO.getEndDate());
            entity.setSettlementCycle(settlementCycle);
            entity.setStatus(status);
            entity.setTotalAmount(importDTO.getTotalAmount());
            entity.setRemark(importDTO.getRemark());

            orderEntities.add(entity);
        }
        
        // 批量保存订单数据
        if (!orderEntities.isEmpty()) {
            orderService.saveBatch(orderEntities);
        }
    }
    
    /**
     * 获取项目名称与ID的映射
     */
    private Map<String, Long> getProjectNameIdMap() {
        List<AttProjectEntity> projects = projectService.list();
        Map<String, Long> projectMap = new HashMap<>(projects.size());
        for (AttProjectEntity project : projects) {
            projectMap.put(project.getProjectName(), project.getProjectId());
        }
        return projectMap;
    }
    
    /**
     * 获取供应商名称与ID的映射
     */
    private Map<String, Long> getSupplierNameIdMap() {
        List<AttSupplierEntity> suppliers = supplierService.list();
        Map<String, Long> supplierMap = new HashMap<>(suppliers.size());
        for (AttSupplierEntity supplier : suppliers) {
            supplierMap.put(supplier.getSupplierName(), supplier.getSupplierId());
        }
        return supplierMap;
    }
} 